package cn.tjnext.apply.service;

import cn.tjnext.apply.dao.AbstractEntityDao;
import cn.tjnext.apply.entity.AbstractEntity;
import cn.tjnext.apply.repositories.AbstractRepository;
import cn.tjnext.apply.web.model.PageModel;
import org.apache.commons.lang3.StringUtils;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.util.List;

@Service
@Transactional(readOnly = true)
public abstract class AbstractService<T extends AbstractEntity, R extends AbstractRepository<T>, D extends AbstractEntityDao<T, R>> {

    //  Fields
    @PersistenceContext
    protected EntityManager entityManager;

    //  Abstract methods
    protected abstract D getDao();

    //  Public methods
    public T findOne(long id) {
        return getDao().findOne(id);
    }

    public Page<T> findList(int page, int pageSize) {
        return getDao().findAllOrderByDefault(new PageRequest(page, pageSize));
    }

    public List<T> findList() {
        return (List<T>) getDao().findAllOrderByDefault();
    }

    public long count() {
        return getDao().count();
    }

    @Transactional(readOnly = false)
    public void delete(long id) throws Exception {
        getDao().delete(id);
    }

    public Page<T>  findAllByPage(PageModel pageModel, int pageSize) {
        int page = 1;
        String keyword = pageModel != null ? pageModel.getKeyWord() : "";
        if (pageModel != null && pageModel.getPage() > 1) {
            page = pageModel.getPage();
        }

        Pageable pageable = new PageRequest(page - 1, pageSize, getDao().getDefaultSorting());
        if (StringUtils.isNotBlank(keyword))
            return getDao().searchByKeyword(keyword, pageable);
        else {
            return getDao().findAllOrderByDefault(pageable);
        }
    }

    @Transactional(readOnly = false)
    public T createOrSave(T entity) throws Exception {
        return getDao().createOrSave(entity);
    }
}
